"""
预约相关API
"""

from flask import request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
from datetime import datetime, timedelta
from app import db
from app.models import Appointment, User, Department, Resource, ResourceAssignment
from app.api import api_bp
from app.scheduling import HybridScheduler
from app import celery

@api_bp.route('/appointments', methods=['POST'])
@jwt_required()
def create_appointment():
    """创建预约"""
    data = request.get_json()
    user_id = get_jwt_identity()
    
    # 验证必填字段
    required_fields = ['department_id', 'appointment_type', 'scheduled_time']
    for field in required_fields:
        if field not in data:
            return jsonify({'error': f'缺少必填字段: {field}'}), 400
    
    # 验证科室是否存在
    department = Department.query.get(data['department_id'])
    if not department:
        return jsonify({'error': '科室不存在'}), 400
    
    # 创建预约
    appointment = Appointment(
        patient_id=user_id,
        department_id=data['department_id'],
        appointment_type=data['appointment_type'],
        scheduled_time=datetime.fromisoformat(data['scheduled_time'].replace('Z', '+00:00')),
        duration=data.get('duration', 30),
        priority=data.get('priority', 1),
        notes=data.get('notes', '')
    )
    
    db.session.add(appointment)
    db.session.commit()
    
    # 异步执行调度
    schedule_appointment.delay(appointment.id)
    
    return jsonify({
        'appointment_id': appointment.id,
        'message': '预约创建成功，正在为您安排最优时段'
    }), 201

@api_bp.route('/appointments', methods=['GET'])
@jwt_required()
def get_appointments():
    """获取预约列表"""
    user_id = get_jwt_identity()
    user = User.query.get(user_id)
    
    if not user:
        return jsonify({'error': '用户不存在'}), 404
    
    # 根据用户角色返回不同的预约列表
    if user.role == 'patient':
        appointments = Appointment.query.filter_by(patient_id=user_id).all()
    elif user.role == 'doctor':
        # 医生可以看到自己科室的预约
        appointments = Appointment.query.join(Department).filter(
            Department.id == user.doctor_schedules.first().department_id
        ).all()
    else:
        # 管理员可以看到所有预约
        appointments = Appointment.query.all()
    
    result = []
    for appointment in appointments:
        result.append({
            'id': appointment.id,
            'patient_name': appointment.patient.username,
            'department_name': appointment.department.name,
            'appointment_type': appointment.appointment_type,
            'scheduled_time': appointment.scheduled_time.isoformat(),
            'duration': appointment.duration,
            'status': appointment.status,
            'priority': appointment.priority,
            'notes': appointment.notes,
            'created_at': appointment.created_at.isoformat()
        })
    
    return jsonify(result)

@api_bp.route('/appointments/<int:appointment_id>', methods=['GET'])
@jwt_required()
def get_appointment(appointment_id):
    """获取单个预约详情"""
    user_id = get_jwt_identity()
    user = User.query.get(user_id)
    
    appointment = Appointment.query.get(appointment_id)
    if not appointment:
        return jsonify({'error': '预约不存在'}), 404
    
    # 权限检查
    if user.role == 'patient' and appointment.patient_id != user_id:
        return jsonify({'error': '无权限访问'}), 403
    
    # 获取资源分配信息
    assignments = []
    for assignment in appointment.resource_assignments:
        assignments.append({
            'resource_id': assignment.resource_id,
            'resource_name': assignment.resource.name,
            'start_time': assignment.start_time.isoformat(),
            'end_time': assignment.end_time.isoformat(),
            'status': assignment.status
        })
    
    return jsonify({
        'id': appointment.id,
        'patient_name': appointment.patient.username,
        'department_name': appointment.department.name,
        'appointment_type': appointment.appointment_type,
        'scheduled_time': appointment.scheduled_time.isoformat(),
        'duration': appointment.duration,
        'status': appointment.status,
        'priority': appointment.priority,
        'notes': appointment.notes,
        'assignments': assignments,
        'created_at': appointment.created_at.isoformat()
    })

@api_bp.route('/appointments/<int:appointment_id>/cancel', methods=['POST'])
@jwt_required()
def cancel_appointment(appointment_id):
    """取消预约"""
    user_id = get_jwt_identity()
    
    appointment = Appointment.query.get(appointment_id)
    if not appointment:
        return jsonify({'error': '预约不存在'}), 404
    
    # 权限检查
    if appointment.patient_id != user_id:
        return jsonify({'error': '无权限操作'}), 403
    
    if appointment.status == 'cancelled':
        return jsonify({'error': '预约已取消'}), 400
    
    # 取消预约
    appointment.status = 'cancelled'
    
    # 释放资源
    for assignment in appointment.resource_assignments:
        assignment.status = 'cancelled'
    
    db.session.commit()
    
    return jsonify({'message': '预约已取消'})

@api_bp.route('/appointments/available-slots', methods=['GET'])
@jwt_required()
def get_available_slots():
    """获取可用时段"""
    department_id = request.args.get('department_id', type=int)
    date = request.args.get('date')
    
    if not department_id or not date:
        return jsonify({'error': '缺少必填参数'}), 400
    
    # 获取指定日期的可用时段
    target_date = datetime.fromisoformat(date)
    start_time = target_date.replace(hour=8, minute=0, second=0, microsecond=0)
    end_time = target_date.replace(hour=18, minute=0, second=0, microsecond=0)
    
    # 查询已占用的时段
    occupied_slots = db.session.query(ResourceAssignment.start_time, ResourceAssignment.end_time)\
        .join(Resource)\
        .filter(Resource.department_id == department_id)\
        .filter(ResourceAssignment.start_time >= start_time)\
        .filter(ResourceAssignment.start_time < end_time)\
        .all()
    
    # 生成可用时段
    available_slots = []
    current_time = start_time
    
    while current_time < end_time:
        slot_end = current_time + timedelta(minutes=30)
        
        # 检查时段是否被占用
        is_occupied = False
        for occupied_start, occupied_end in occupied_slots:
            if not (slot_end <= occupied_start or current_time >= occupied_end):
                is_occupied = True
                break
        
        if not is_occupied:
            available_slots.append({
                'start_time': current_time.isoformat(),
                'end_time': slot_end.isoformat()
            })
        
        current_time += timedelta(minutes=30)
    
    return jsonify(available_slots)

@celery.task
def schedule_appointment(appointment_id):
    """异步调度预约"""
    try:
        appointment = Appointment.query.get(appointment_id)
        if not appointment:
            return
        
        # 获取相关资源
        resources = Resource.query.filter_by(
            department_id=appointment.department_id,
            status='available'
        ).all()
        
        if not resources:
            return
        
        # 执行调度
        scheduler = HybridScheduler()
        result = scheduler.optimize(
            resources=[{
                'id': r.id,
                'name': r.name,
                'resource_type': r.resource_type,
                'department_id': r.department_id,
                'status': r.status
            } for r in resources],
            appointments=[{
                'id': appointment.id,
                'department_id': appointment.department_id,
                'preferred_time': appointment.scheduled_time,
                'duration': appointment.duration,
                'priority': appointment.priority
            }],
            objectives=['resource_utilization', 'patient_wait_time', 'fairness']
        )
        
        # 保存调度结果
        solution = result['solution']
        for resource_id, assignments in solution.get('assignments', {}).items():
            for assignment in assignments:
                resource_assignment = ResourceAssignment(
                    appointment_id=appointment.id,
                    resource_id=resource_id,
                    start_time=assignment['start_time'],
                    end_time=assignment['end_time']
                )
                db.session.add(resource_assignment)
        
        appointment.status = 'confirmed'
        db.session.commit()
        
    except Exception as e:
        print(f"调度失败: {e}")
        appointment.status = 'failed'
        db.session.commit()
